#include "tcp_sock.h"

#include "log.h"

#include <unistd.h>

// tcp server application, listens to port (specified by arg) and serves only one
// connection request
void *tcp_server(void *arg)
{
	u16 port = *(u16 *)arg;
	struct tcp_sock *tsk = alloc_tcp_sock();

	struct sock_addr addr;
	addr.ip = htonl(0);
	addr.port = port;
	if (tcp_sock_bind(tsk, &addr) < 0) {
		log(ERROR, "tcp_sock bind to port %hu failed", ntohs(port));
		exit(1);
	}

	if (tcp_sock_listen(tsk, 3) < 0) {
		log(ERROR, "tcp_sock listen failed");
		exit(1);
	}

	log(DEBUG, "listen to port %hu.", ntohs(port));

	struct tcp_sock *csk = tcp_sock_accept(tsk);

	log(DEBUG, "accept a connection.");

	//ready to read
	FILE *file = fopen("server-output.dat", "wb");

	if (!file) {
		log(ERROR, "Failed to open file for writing.");
		exit(1);
	}

	
	int rcv_len=0;

	while(1){
		char rcv_buf[TCP_MSS];
		//sleep for reading data
		
		rcv_len=tcp_sock_read(csk, rcv_buf, TCP_MSS);

		if (rcv_len < 0) {
			log(ERROR, "No data read or error occurred.");
			break;
		}

		if (fwrite(rcv_buf, 1, rcv_len, file) != rcv_len) {
			log(ERROR, "Failed to write data to file.");
			break;
		}

		log(INFO,"server: read %d bytes from client.", rcv_len);

		//check if the peer socket is closed, file transmit end
		if(rcv_len==0){
			log(INFO, "server: connection closed. Exiting.");
			break;
		}
	}

	if (rcv_len < 0) {
		log(ERROR, "Error reading from socket.");
	}

	fclose(file);
	log(WARNING, "File has been written and closed.");
	

	sleep(5);

	tcp_sock_close(csk);
	log(WARNING, "server has been closed");

	return NULL;
}

// tcp client application, connects to server (ip:port specified by arg), each
// time sends one bulk of data and receives one bulk of data 
void *tcp_client(void *arg)
{
	struct sock_addr *skaddr = arg;

	struct tcp_sock *tsk = alloc_tcp_sock();

	if (tcp_sock_connect(tsk, skaddr) < 0) {
		log(ERROR, "tcp_sock connect to server ("IP_FMT":%hu)failed.", \
				NET_IP_FMT_STR(skaddr->ip), ntohs(skaddr->port));
		exit(1);
	}

	log(DEBUG, "connect to server ("IP_FMT":%hu) success.", \
			NET_IP_FMT_STR(skaddr->ip), ntohs(skaddr->port));

	//ready to send data 设置为最大segment size (MSS)的一半
	char buf[TCP_MSS/2];

	int snt_amt=0;
    while (1) {
		FILE *file = fopen("client-input.dat", "rb");
		if (!file) {
			log(ERROR, "Failed to open file for reading.");
			break;
		}

		
		while (1) {
			size_t bytes_read;
			while ((bytes_read = fread(buf, 1, sizeof(buf), file)) > 0) {
				log(DEBUG, "Read %zu bytes from file.", bytes_read);

				// Send the data to the server
				int bytes_sent = tcp_send_data(tsk, buf, bytes_read);
				if (bytes_sent < 0) {
					log(ERROR, "Failed to send data to server.");
					break;
				}
				else{
					log(INFO,"Send %dth batch: %d data to server,seq is %u", snt_amt, bytes_sent,tsk->snd_nxt);
					snt_amt++;
				}
			}

			if (feof(file)) {
				//log(DEBUG, "End of file reached.");
				break;
			} else if (ferror(file)) {
				log(ERROR, "Error reading from file.");
				break;
			}
		}

		fclose(file);
		log(INFO, "tcp_client: File closed.");
		
		break;
	}
	
	sleep(1);

	tcp_sock_close(tsk);
	log(INFO, "client has been closed.");

	return NULL;
}
